package server

import (
	"errors"
	"fmt"
	"github.com/google/uuid"
	"gorm.io/gorm"
	"onerk4/zg5yk/ordering/common/dao/mysql"
	"onerk4/zg5yk/ordering/common/global"
	"onerk4/zg5yk/ordering/common/model"
	"onerk4/zg5yk/ordering/common/pkg"
	"onerk4/zg5yk/ordering/common/proto/order"
)

func CreateOrder(req *order.CreateOrderRequest) (*order.CreateOrderResponse, error) {
	info, err := mysql.QueryTakeoutInfo(req.TakeoutId)
	if err != nil {
		return nil, err
	}
	if num := info.MealProductsStock - int(req.Num); num < 0 {
		return nil, errors.New("库存不足")
	}
	orderSn := uuid.New().String()
	orderInfo, err := mysql.QueryOrderInfo(orderSn)
	if err != nil {
		return nil, err
	}
	if orderInfo.ID != 0 {
		return nil, errors.New("同一订单号不可重复下单")
	}
	if req.CouponId != 0 {
		coupon, err := mysql.QueryUserCoupon(req.CouponId, req.UserId)
		if err != nil {
			return nil, err
		}
		if coupon.Status != 2 || coupon.MinimumAvailable > info.MealProductsPrice*float64(req.Num) {
			return nil, errors.New("该优惠卷不可用")
		}

		o := model.Order{
			Model:             gorm.Model{},
			OrderSn:           orderSn,
			Uid:               int(req.UserId),
			TakeoutId:         int(req.TakeoutId),
			MealProductsName:  info.MealProductsName,
			MealProductsImage: info.MealProductsImage,
			MealProductsPrice: info.MealProductsPrice * float64(req.Num),
			PayPrice:          info.MealProductsPrice*float64(req.Num) - coupon.CouponLimit,
			DiscountPrice:     coupon.CouponLimit,
			Num:               int(req.Num),
			Notes:             req.Notes + "，（使用优惠卷）",
			Status:            3,
		}
		err = mysql.CreateOrder(&o)
		if err != nil {
			return nil, err
		}
		sprintf := fmt.Sprintf("%.2f", info.MealProductsPrice*float64(req.Num)-coupon.CouponLimit)
		pay := pkg.NewAliPay()
		payUrl := pay.Pay(info.MealProductsName, orderSn, sprintf)

		err = mysql.UpdateUserCoupon(req.UserId, req.CouponId, 1)
		if err != nil {
			return nil, errors.New("修改优惠卷状态失败")
		}

		return &order.CreateOrderResponse{Success: payUrl}, nil
	}

	o := model.Order{
		Model:             gorm.Model{},
		OrderSn:           orderSn,
		Uid:               int(req.UserId),
		TakeoutId:         int(req.TakeoutId),
		MealProductsName:  info.MealProductsName,
		MealProductsImage: info.MealProductsImage,
		MealProductsPrice: info.MealProductsPrice,
		PayPrice:          info.MealProductsPrice * float64(req.Num),
		DiscountPrice:     0.00,
		Num:               int(req.Num),
		Notes:             req.Notes + "没有使用优惠卷",
		Status:            3,
	}
	err = mysql.CreateOrder(&o)
	if err != nil {
		return nil, err
	}
	sprintf := fmt.Sprintf("%.2f", info.MealProductsPrice*float64(req.Num))
	pay := pkg.NewAliPay()
	payUrl := pay.Pay(info.MealProductsName, orderSn, sprintf)

	return &order.CreateOrderResponse{Success: payUrl}, nil
}

func Callback(req *order.CallbackRequest) (*order.CallbackResponse, error) {
	info, err := mysql.QueryOrderInfo(req.OrderSn)
	if err != nil {
		return nil, err
	}

	takeoutInfo, err := mysql.QueryTakeoutInfo(int64(info.TakeoutId))
	if err != nil {
		return nil, err
	}

	user, err := mysql.QueryUserInfoByUserId(info.Uid)
	if err != nil {
		return nil, err
	}

	tx := global.DB.Begin()
	err = mysql.UpdateOrderSta(req.OrderSn, req.OrderSn, tx)
	if err != nil {
		tx.Rollback()
		return nil, errors.New("修改订单状态失败")
	}

	num := takeoutInfo.MealProductsStock - info.Num
	err = mysql.UpdateTakeoutStock(info.TakeoutId, num, tx)
	if err != nil {
		tx.Rollback()
		return nil, errors.New("扣减库存失败")
	}

	Points := user.Points + info.PayPrice
	err = mysql.UpdatePoints(info.Uid, Points, tx)
	if err != nil {
		tx.Rollback()
		return nil, err
	}

	tx.Commit()
	return nil, nil
}

func ShowOrderList(req *order.ShowOrderListRequest) (*order.ShowOrderListResponse, error) {

	list, err := mysql.QueryOrderList(req.UserId)
	if err != nil {
		return nil, err
	}

	var items []*order.OrderItem

	for _, m := range list {
		items = append(items, &order.OrderItem{
			Id:                int64(m.ID),
			OrderSn:           m.OrderSn,
			Uid:               int64(m.Uid),
			TakeoutId:         int64(m.TakeoutId),
			MealProductsName:  m.MealProductsName,
			MealProductsImage: m.MealProductsImage,
			MealProductsPrice: float32(m.MealProductsPrice),
			PayPrice:          float32(m.PayPrice),
			DiscountPrice:     float32(m.DiscountPrice),
			Num:               int64(m.Num),
			Notes:             m.Notes,
			Status:            int64(m.Status),
		})
	}

	return &order.ShowOrderListResponse{List: items}, nil
}
